其實 Rails 裡面暗藏了很多可以自行定義的東西,像我們前面介紹過 validator、attribute 資料轉換器、callbacks 等等。
這次要來介紹的是,在 view 裡面常用到的 helper method form_for
or form_with
可以配合使用的 自訂義 form builder!
其實很簡單,說破不值錢。
只要像這樣建立一個 class 繼承自 ActionView::Helpers::FormBuilder
,就可以在裡面加上您自定義的 form method:
class MyFormBuilder < ActionView::Helpers::FormBuilder
def give_me_five
"其實是手掌的 emoji 只是這邊不知道為什麼顯示不出來"
end
end
然後在 form_for 的 options 裡面加上 key :builder
並把你的 form builder class 指定進去,並且使用你定義好的 method:
<%= form_for @user, builder: MyFormBuilder do |form| %>
<div><%= form.give_me_five %></div>
<div><%= form.submit 'Submit' %></div>
<% end %>
你就會看到你的 form 長這樣:
這樣做有什麼好處?有什麼應用範圍?
通常情況,如果我們想要在 view 使用一套邏輯來生成畫面,但又想共用,或者不想把 erb 檔弄髒,我們會定義 helper method。
但 helper method 本身其實也有他的極限,尤其當你需要額外把 |form|
這個 form builder 也一起傳入 method 去做畫面的 render 導致你傳入的 arguments 過多,導致可讀性下降的時候。
這時候,把 method 搬到 自定義 form builder 裡面,這樣你至少可以省下 form builder
以及 form object
兩個 argument,因為通過 form_for
其實就已經把你的 form object 給傳進 form builder 裡面了。
在 form builder 裡面,你可以透過 @object
這個實體變數來讀取你傳入的 form object,比如:
class MyFormBuilder < ActionView::Helpers::FormBuilder
def welcome_message
if @object.new_record?
"Hello new friend!!"
else
"It's good to see ya!!"
end
end
end
然後我的 view 就可以這樣規劃:
<%= form_for @user, builder: MyFormBuilder do |form| %>
<div><%= form.welcome_message %></div>
<div><%= form.submit 'Submit' %></div>
<% end %>
你就會看到你的 form 長這樣:
當然,都已經繼承了,那肯定也可以 over write 像是 select
, collection_check_boxes
之類的 form helper methods。這兩個筆者我都有玩過 over write XD